package com.syuchen.server.http;

import com.syuchen.protocol.http.Request;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

public class RequestParser {

    /**
     * 将请求数据流解析为Request对象
     */
    public static Request parseRequestStream(InputStream inputStream) throws IOException {
        Request request = new Request();
        BufferedReader requestReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));

        parseFirstLine(request, requestReader);
        parseHeaders(request,requestReader);
        parseBody(request,requestReader);

        return request;
    }

    private static void parseFirstLine(Request request, BufferedReader requestReader) throws IOException {
        String firstLine = requestReader.readLine();
        String[] firstLineStrings = firstLine.split("\\s");
        request.setMethod(firstLineStrings[0]);
        request.setUri(firstLineStrings[1]);
        request.setVersion(firstLineStrings[2]);
    }

    private static void parseHeaders(Request request, BufferedReader requestReader) throws IOException {
        Map<String, String> headers = new HashMap<>();
        String headerString = requestReader.readLine();
        while (!headerString.equals("")) {
            String[] strs = headerString.split(":");
            headers.put(strs[0].trim(), strs[1].trim());
            headerString = requestReader.readLine();
        }
        request.setHeaders(headers);
    }

    /**
     * TCP长连接是通过流的方式传递数据，消息之间没有边界，会出现粘包的问题
     * 而按照http协议，请求体后没有结束标识符（也不应该有标识符，如果有的话则限制了请求体数据中不能包含有标识符字符），
     * 因此这里只能通过约定请求体的大小来读取数据
     */
    private static void parseBody(Request request, BufferedReader requestReader) throws IOException {
        //todo Content-Length的单位是字节
        int contentLength = Integer.parseInt(request.getHeaders().getOrDefault("Content-Length", "0"));
        if (contentLength == 0) {
            return;
        }
        char[] body = new char[contentLength];
        int read = requestReader.read(body);
        request.setBody(new String(body));
    }

}
